﻿using System;
using System.Collections.Generic;
using System.Reflection;

namespace Flagwind.Data
{
	internal class RemoteLoader : MarshalByRefObject
	{
		private Assembly assembly;

		public void LoadAssembly(string fullName)
		{
			assembly = Assembly.LoadFrom(fullName);
		}

		public string FullName
		{
			get
			{
				return assembly.FullName;
			}
		}

		public string ErrorMessage
		{
			get;
			private set;
		}

		public bool IsEntityClass
		{
			get;
			private set;
		}

		public string[] GetAllTypeNames()
		{
			List<string> list = new List<string>();
			foreach(var t in assembly.GetTypes())
			{
				list.Add(t.FullName + "," + t.Name);
			}
			return list.ToArray();
		}

		public List<KeyValuePair<string, string>> GetAllPropertyNames(string className)
		{
			Type objType = null;
			this.ErrorMessage = "";
			foreach(var t in assembly.GetTypes())
			{
				if(t.FullName == className || t.Name == className)
				{
					objType = t;
					break;
				}
			}
			if(objType != null)
			{
				this.IsEntityClass = Activator.CreateInstance(objType) is IEntity;
				List<KeyValuePair<string, string>> dataList = new List<KeyValuePair<string, string>>();
				//
				foreach(var prop in objType.GetProperties(BindingFlags.Instance | BindingFlags.Public))
				{
					if(prop.CanRead && prop.CanWrite)
					{
						var propType = prop.PropertyType;
						if(propType.IsValueType || propType == typeof(string))
						{
							string info = prop.Name.PadRight(20) + "|" + Type.GetTypeCode(propType).ToString();
							dataList.Add(new KeyValuePair<string, string>(info, prop.Name));
						}
					}
				}
				return dataList;
			}
			this.IsEntityClass = false;
			this.ErrorMessage = "未找到类型 " + className;
			return null;
		}

		public object Invoke(string fullClassName, string methodName, object[] paraValues)
		{
			ErrorMessage = "";
			Type objType = null;
			foreach(var t in assembly.GetTypes())
			{
				if(t.FullName == fullClassName || t.Name == fullClassName)
				{
					objType = t;
					break;
				}
			}
			if(objType != null)
			{
				var objMethod = objType.GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public);
				if(objMethod != null)
				{
					try
					{
						object instance = Activator.CreateInstance(objType);
						return objMethod.Invoke(instance, paraValues);
					}
					catch(Exception ex)
					{
						ErrorMessage = ex.Message;
					}
				}
				else
				{
					ErrorMessage = "未找到方法 " + methodName;
				}
			}
			else
			{
				ErrorMessage = "未找到类型 " + fullClassName;
			}
			return null;
		}

		/// <summary>
		/// 根据指定的实体类中的属性名，返回实体类的表名称和属性对应的字段名称
		/// </summary>
		/// <param name="fullClassName">实体类名称</param>
		/// <param name="propertyName">属性名称</param>
		/// <returns>返回实体类的表名称和属性对应的字段名称</returns>
		public string[] TableFieldName(string fullClassName, string propertyName)
		{
			ErrorMessage = "";
			Type objType = null;
			foreach(var t in assembly.GetTypes())
			{
				if(t.FullName == fullClassName || t.Name == fullClassName)
				{
					objType = t;
					break;
				}
			}
			if(objType != null)
			{
				EntityInfo ef = new EntityInfo(objType);
				string fieldName = ef.GetFieldName(propertyName);
				if(fieldName == null)
				{
					this.ErrorMessage = "属性 " + propertyName + " 不是实体类属性，无法找到对应的属性字段。";
					return null;
				}
				else
				{
					string[] arr =
					{
						ef.TableName, fieldName
					};
					return arr;
				}
			}
			ErrorMessage = "未找到类型 " + fullClassName;
			return null;
		}
	}
}